package indi.h.security.encryption.sym;

import java.io.IOException;
import java.security.AlgorithmParameters;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;

import indi.h.security.encryption.util.KeysConvert;

public class PBECryptImp extends SymCryptImp implements PBECrypt {
	private AlgorithmParameters algorithmParameters;

	protected PBECryptImp() {
		// TODO Auto-generated constructor stub

	}

	@Override
	public void customInit() {
		// TODO Auto-generated method stub
		if (secretKey == null) {
			params.setSecretKey(params.getPassword().getBytes(params.getCode()));
			secretKey = createKeySpec();
		}
		try {
			if (((PBECryptParameter) params).getAlgorithmParameters() != null) {
				createAlgorithmParameters();
				return;
			}
			PBEParameterSpec pbeParameterSpec = new PBEParameterSpec(((PBECryptParameter) params).getSalt(),
					params.getLength());
			cipher.init(Cipher.ENCRYPT_MODE, secretKey, pbeParameterSpec);
			((PBECryptParameter) params).setAlgorithmParameters(getAlgorithmParameters());
			createAlgorithmParameters();
		} catch (InvalidKeyException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvalidAlgorithmParameterException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	protected void createAlgorithmParameters() {
		algorithmParameters = KeysConvert.createAlgorithmParameters(params.getCipherAlgorithm(),
				((PBECryptParameter) params).getAlgorithmParameters());
	}

	@Override
	public SecretKey createKeySpec() {
		// TODO Auto-generated method stub
		PBEKeySpec pks = new PBEKeySpec(new String(params.getSecretKey(), params.getCode()).toCharArray());
		try {
			return SecretKeyFactory.getInstance(params.getAlgorithm()).generateSecret(pks);
		} catch (InvalidKeySpecException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			// TODOAuto-generated catch block
			e.printStackTrace();
		}
		return null;
	}

	@Override
	public void beforeEncrypt() {
		// TODO Auto-generated method stub
		try {
			cipher.init(Cipher.ENCRYPT_MODE, secretKey, algorithmParameters);
		} catch (InvalidKeyException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvalidAlgorithmParameterException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Override
	public void beforeDecrypt() {
		// TODO Auto-generated method stub
		try {
			cipher.init(Cipher.DECRYPT_MODE, secretKey, algorithmParameters);
		} catch (InvalidKeyException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvalidAlgorithmParameterException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Override
	public byte[] getSalt() {
		// TODO Auto-generated method stub
		return ((PBECryptParameter) params).getSalt();
	}

	@Override
	public byte[] getAlgorithmParameters() {
		// TODO Auto-generated method stub
		try {
			return cipher.getParameters().getEncoded();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}

}
